#include <QTest>
#include <QSignalSpy>
#include <QVariant>

#include "ShowLoader_Test.h"

#include "ShowLoader.h"
#include "MockShowGuiInterface.h"
#include "ShowFileFactory.h"
#include "MediaListModel.h"
#include "SequenceModel.h"
#include "sequenceitem.h"
#include "lightpresetdata.h"
#include "lightpresetmodel.h"
#include "LightPresetFactory.h"
#include "MockScriptEngine.h"
#include "MockMediaSourceFactory.h"
#include "modelViewRules.h"


#define  FINAL_TEST_PATH  "/ShowFileParser/test/BigFinalTest.mts"
#define  FEW_LIGHT_TEST_PATH  "/ShowFileParser/test/TestFewLights.mts"

/** number of DMX channels for this test */
#define CHANNELS_FOR_TEST  10

ShowLoader_Test::ShowLoader_Test(QObject *parent) :
   QObject(parent)
{
}

void ShowLoader_Test::init()
{
   QStringList notifyLog;
   m_guiInterface = new MockShowGuiInterface( notifyLog, QString("Name.mts"));

   LightPresetFactory *presetFactory = new LightPresetFactory( this);
   m_lightModel = new LightPresetModel( CHANNELS_FOR_TEST, presetFactory, this);

   MockMediaSourceFactory *mediaFactory = new MockMediaSourceFactory();
   m_mediaModel = new MediaListModel( mediaFactory, this);

   m_mockScriptEngine = new MockScriptEngine();
   m_parserFactory = new ShowFileFactory( CHANNELS_FOR_TEST, this);

   m_sequenceItemList = new QList<SequenceItem *>();
   m_sequenceModel = new SequenceModel( *m_sequenceItemList, this);

   m_showLoader = NULL;
}

void ShowLoader_Test::cleanup()
{
   if (m_showLoader != NULL)
   {
      delete m_showLoader;
   }

   delete m_sequenceModel;
   delete m_sequenceItemList;
   delete m_mockScriptEngine;
   delete m_mediaModel;
   delete m_lightModel;
   delete m_guiInterface;
}


void ShowLoader_Test::testInit()
{
   m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, m_mediaModel,
                                  m_lightModel, m_sequenceModel, m_mockScriptEngine, this);

   QVERIFY( m_showLoader != NULL);
}

void ShowLoader_Test::testLoadFile()
{
   m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, m_mediaModel,
                                  m_lightModel, m_sequenceModel, m_mockScriptEngine, this);

   QSignalSpy spyShowNameChanged( m_showLoader, SIGNAL(showNameChanged(QString)));
   QSignalSpy spyNewSearchPath( m_showLoader, SIGNAL(newSearchPath(QString)));
   QSignalSpy spyScriptContent( m_showLoader, SIGNAL(scriptContent(QString)));

   /* main function that parses show file */
   m_showLoader->LoadShow( QString(PROJECT_PATH) + FINAL_TEST_PATH);

   QCOMPARE( spyShowNameChanged.count(), 1);
   QVERIFY( spyShowNameChanged.at(0).at(0).toString().contains("BigFinalTest.mts"));

   QCOMPARE( spyNewSearchPath.count(), 1);
   QCOMPARE( spyScriptContent.count(), 1);

   QCOMPARE( m_mediaModel->rowCount(), 3);
   QCOMPARE( m_lightModel->rowCount(), 3);
}

void ShowLoader_Test::testLoadInvalidFile()
{
   m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, m_mediaModel,
                                  m_lightModel, m_sequenceModel, m_mockScriptEngine, this);

   bool exceptionRaised = false;

   try
   {
      m_showLoader->LoadShow("/Fake/Path/file.mts");
   }
   catch( QString &err)
   {
      exceptionRaised = true;
      QCOMPARE( err.toLatin1(), QString("file /Fake/Path/file.mts does not exist").toLatin1());
   }

   QVERIFY( exceptionRaised == true);
}


void ShowLoader_Test::testInvalidParserFactory()
{
   bool exceptionGenerated = false;

   try
   {
      m_showLoader = new ShowLoader( *m_guiInterface, NULL, m_mediaModel,
                                     m_lightModel, m_sequenceModel, m_mockScriptEngine, this);
   }
   catch( QString & err)
   {
      exceptionGenerated = true;
      QVERIFY2( err.contains("Assert fail:"), err.toLatin1());
   }

   QVERIFY( exceptionGenerated == true);
}


void ShowLoader_Test::testInvalidMediaModel()
{
   bool exceptionGenerated = false;

   try
   {
      m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, NULL,
                                     m_lightModel, m_sequenceModel, m_mockScriptEngine, this);
   }
   catch( QString & err)
   {
      exceptionGenerated = true;
      QVERIFY2( err.contains("Assert fail:"), err.toLatin1());
   }

   QVERIFY( exceptionGenerated == true);
}


void ShowLoader_Test::testInvalidLightModel()
{
   bool exceptionGenerated = false;

   try
   {
      m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, m_mediaModel,
                                     NULL, m_sequenceModel, m_mockScriptEngine, this);
   }
   catch( QString & err)
   {
      exceptionGenerated = true;
      QVERIFY2( err.contains("Assert fail:"), err.toLatin1());
   }

   QVERIFY( exceptionGenerated == true);
}


void ShowLoader_Test::testInvalidScriptEngine()
{
   bool exceptionGenerated = false;

   try
   {
      m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, m_mediaModel,
                                     m_lightModel, m_sequenceModel, NULL, this);
   }
   catch( QString & err)
   {
      exceptionGenerated = true;
      QVERIFY2( err.contains("Assert fail:"), err.toLatin1());
   }

   QVERIFY( exceptionGenerated == true);
}

void ShowLoader_Test::testFewLightValues()
{
   bool exceptionRised = false;

   try
   {
      m_showLoader = new ShowLoader( *m_guiInterface, m_parserFactory, m_mediaModel,
                                     m_lightModel, m_sequenceModel, m_mockScriptEngine, this);

      /* missing lights are padded with 0 */
      m_showLoader->LoadShow( QString(PROJECT_PATH) + FEW_LIGHT_TEST_PATH);
   }
   catch( QString & /*err*/)
   {
      exceptionRised = true;
   }

   QVERIFY(! exceptionRised);
}

